import requests
import json
import time
import logging
from functools import wraps
from django.conf import settings

logger = logging.getLogger(__name__)


def retry_on_failure(max_retries=3, delay=1):
    """重试装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_retries - 1:
                        logger.error(f"重试{max_retries}次后仍然失败: {str(e)}")
                        raise e
                    logger.warning(f"第{attempt + 1}次调用失败，{delay * (2 ** attempt)}秒后重试: {str(e)}")
                    time.sleep(delay * (2 ** attempt))  # 指数退避
            return None
        return wrapper
    return decorator


class DoubaoLLMService:
    """火山引擎豆包大模型服务类 - 使用统一API Key + Model ID调用"""
    
    def __init__(self):
        # 使用统一的API Key
        self.api_key = getattr(settings, 'ARK_API_KEY', 'your-api-key-here')
        self.base_url = getattr(settings, 'ARK_BASE_URL', 'https://ark.cn-beijing.volces.com/api/v3')
        self.model_id = getattr(settings, 'ARK_TEXT_MODEL_ID', 'doubao-seed-1-6-vision-250815')
        
        # 验证配置
        if self.api_key == 'your-api-key-here':
            logger.warning("使用默认API_KEY，请在settings中配置正确的ARK_API_KEY")
    
    @retry_on_failure(max_retries=3, delay=1)
    def generate_text(self, prompt, max_tokens=1000, temperature=0.7, messages=None, tools=None, thinking=False):
        """
        调用火山引擎API生成文本 - 使用标准API Key + Model ID
        支持多种输入格式和高级功能
        
        Args:
            prompt: 输入提示词（用于简单文本生成）
            max_tokens: 最大生成token数
            temperature: 生成温度，控制随机性
            messages: 对话消息数组（用于多轮对话或多模态输入）
            tools: 工具配置（函数调用）
            thinking: 是否启用思维模式
            
        Returns:
            dict: 包含生成结果的字典
        """
        start_time = time.time()
        
        # 使用标准的Authorization Bearer格式
        headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json'
        }
        
        # 构造符合火山引擎API规范的请求体
        payload = self._build_request_payload(prompt, max_tokens, temperature, messages, tools, thinking)
        
        try:
            logger.info(f"开始调用文本生成API，模型: {self.model_id}")
            
            # 调用火山引擎文本生成API
            response = requests.post(
                f'{self.base_url}/chat/completions',
                headers=headers,
                json=payload,
                timeout=60  # 60秒超时
            )
            
            duration = time.time() - start_time
            
            if response.status_code == 200:
                result = response.json()
                
                # 提取生成的内容
                if 'choices' in result and result['choices']:
                    content = result['choices'][0]['message']['content']
                    usage = result.get('usage', {})
                    
                    logger.info(f"文本生成成功 - 耗时: {duration:.2f}s, tokens: {usage.get('total_tokens', 0)}")
                    
                    return {
                        'success': True,
                        'content': content,
                        'usage': usage,
                        'model': result.get('model', self.model_id),
                        'duration': duration
                    }
                else:
                    logger.error(f"API响应格式异常: {result}")
                    return {
                        'success': False,
                        'error': 'API响应格式异常，未找到生成内容',
                        'content': None,
                        'duration': duration
                    }
            else:
                error_msg = f"HTTP {response.status_code}: {response.text}"
                logger.error(f"API调用失败 - {error_msg}")
                return {
                    'success': False,
                    'error': error_msg,
                    'content': None,
                    'duration': duration
                }
                
        except requests.exceptions.Timeout:
            duration = time.time() - start_time
            error_msg = "API调用超时"
            logger.error(f"{error_msg} - 耗时: {duration:.2f}s")
            return {
                'success': False,
                'error': error_msg,
                'content': None,
                'duration': duration
            }
            
        except requests.exceptions.RequestException as e:
            duration = time.time() - start_time
            error_msg = f"网络请求失败: {str(e)}"
            logger.error(f"{error_msg} - 耗时: {duration:.2f}s")
            return {
                'success': False,
                'error': error_msg,
                'content': None,
                'duration': duration
            }
            
        except (KeyError, IndexError, json.JSONDecodeError) as e:
            duration = time.time() - start_time
            error_msg = f"响应解析失败: {str(e)}"
            logger.error(f"{error_msg} - 耗时: {duration:.2f}s")
            return {
                'success': False,
                'error': error_msg,
                'content': None,
                'duration': duration
            }

    def _build_request_payload(self, prompt, max_tokens, temperature, messages, tools, thinking):
        """
        构建符合火山引擎API要求的请求负载
        支持简单文本、多轮对话、多模态输入
        """
        payload = {
            'model': self.model_id,
            'max_tokens': max_tokens,
            'temperature': temperature,
            'stream': False
        }
        
        # 处理messages参数（优先级高于prompt）
        if messages:
            # 验证和处理messages格式
            processed_messages = self._process_messages(messages)
            payload['messages'] = processed_messages
        elif prompt:
            # 简单文本输入
            payload['messages'] = [
                {'role': 'user', 'content': prompt}
            ]
        else:
            raise ValueError("必须提供prompt或messages参数")
        
        # 添加工具支持
        if tools:
            payload['tools'] = tools
            
        # 添加思维模式
        if thinking:
            payload['thinking'] = {'enabled': True}
            
        return payload

    def _process_messages(self, messages):
        """
        处理和验证messages数组，支持多模态输入
        """
        processed = []
        
        for msg in messages:
            if not isinstance(msg, dict) or 'role' not in msg or 'content' not in msg:
                raise ValueError("每个message必须包含role和content字段")
            
            # 验证role值
            valid_roles = ['system', 'user', 'assistant']
            if msg['role'] not in valid_roles:
                raise ValueError(f"role必须是{valid_roles}之一")
            
            processed_msg = {
                'role': msg['role'],
                'content': msg['content']
            }
            
            processed.append(processed_msg)
        
        return processed


def build_enhanced_prompt(module, content_type, user_prompt, params):
    """
    根据模块和内容类型构建增强的提示词
    
    Args:
        module: 功能模块 (creative/academic)
        content_type: 内容类型 (novel/poetry/paper等)
        user_prompt: 用户输入的提示词
        params: 生成参数
        
    Returns:
        str: 增强后的提示词
    """
    
    # 模块提示词模板
    module_templates = {
        'creative': {
            'novel': '你是一位专业的小说作家，擅长创作各种类型的小说。请根据以下要求创作小说内容：',
            'poetry': '你是一位才华横溢的诗人，精通各种诗歌形式。请根据以下要求创作诗歌：',
            'script': '你是一位经验丰富的编剧，熟悉各种剧本格式。请根据以下要求创作剧本：',
            'story': '你是一位优秀的故事作家，善于讲述引人入胜的故事。请根据以下要求创作故事：',
            'copy': '你是一位资深的文案策划师，精通各种营销文案。请根据以下要求创作文案：'
        },
        'academic': {
            'paper': '你是一位学术研究者，具有丰富的学术写作经验。请根据以下要求撰写学术论文内容：',
            'summary': '你是一位学术编辑，擅长撰写精准的学术摘要。请根据以下要求撰写摘要：',
            'reference': '你是一位学术助手，熟悉各种引用格式。请根据以下要求整理参考文献：',
            'report': '你是一位专业的研究员，善于撰写详实的研究报告。请根据以下要求撰写研究报告：'
        }
    }
    
    # 获取对应的模板
    template = module_templates.get(module, {}).get(content_type, '请根据以下要求生成内容：')
    
    # 构建基础提示词
    enhanced_prompt = f"{template}\n\n{user_prompt}"
    
    # 添加额外的参数指导
    if params.get('style'):
        enhanced_prompt += f"\n\n写作风格：{params['style']}"
    if params.get('length'):
        enhanced_prompt += f"\n\n内容长度：{params['length']}"
    if params.get('tone'):
        enhanced_prompt += f"\n\n语调要求：{params['tone']}"
    if params.get('target_audience'):
        enhanced_prompt += f"\n\n目标受众：{params['target_audience']}"
    if params.get('language_style'):
        enhanced_prompt += f"\n\n语言风格：{params['language_style']}"
    
    # 添加格式要求
    enhanced_prompt += "\n\n请确保内容结构清晰，语言流畅，符合相应类型的写作规范。"
    
    return enhanced_prompt